package cn.swing.his.operation.webapi.impl;


import cn.swing.his.affair.service.IAffairService;
import cn.swing.his.common.exception.HisServiceException;
import cn.swing.his.common.web.JsonPage;
import cn.swing.his.common.web.ResponseCode;
import cn.swing.his.log.service.ILogService;
import cn.swing.his.operation.service.IOperationService;
import cn.swing.his.operation.webapi.mapper.OperationMapper;
import cn.swing.his.pojo.affair.vo.MedicineDetailsVO;
import cn.swing.his.pojo.operation.dto.DoctorListDTO;
import cn.swing.his.pojo.operation.dto.OrderSettingDTO;
import cn.swing.his.pojo.operation.dto.PatientSimpleInfoDTO;
import cn.swing.his.pojo.operation.vo.*;
import cn.swing.his.pojo.operation.entity.*;
import cn.swing.his.pojo.user.vo.MedicalRecordVO;
import cn.swing.his.pojo.operation.dto.PatientCheckItemDTO;
import cn.swing.his.pojo.operation.entity.PatientCheckItem;
import cn.swing.his.pojo.operation.vo.OrderSettingVO;
import cn.swing.his.pojo.operation.vo.OutpatientServiceVO;
import cn.swing.his.pojo.operation.vo.PatientSimpleInfoVO;
import cn.swing.his.pojo.operation.vo.SearchOrderVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static cn.swing.his.common.web.ResponseCode.UPDATE_PATIENT_INFO_ERROR;

@Service
@Slf4j
@DubboService
public class OperationServiceImpl implements IOperationService {
    @Autowired
    OperationMapper operationMapper;

//    @DubboReference
//    ILogService logService;

    @DubboReference
    IAffairService affairService;

    /**********************************  insert   *********************************/

    /**
     * 增加一个处方表-药品购买表
     * @return 受影响的行数
     */
    @Override
    public void insertPrescriptionMedicine(PrescriptionMedicineVO prescriptionMedicineVO) {
        PrescriptionMedicine prescriptionMedicine = new PrescriptionMedicine();
        // 根据用户id查出用户最新的处方表
        Integer prescriptionId = operationMapper.getPrescriptionIdByUserId(prescriptionMedicineVO.getUserId());
        // 向处方表中插入总金额
        operationMapper.updateTotalPrice(prescriptionMedicineVO.getTotalPrice(), prescriptionId);
        // 新增一个处方药物购买表
        List<Integer> medicineIds = prescriptionMedicineVO.getMedicineId();
        List<Integer> purchasedNumbers = prescriptionMedicineVO.getPurchasedNumber();
        for (int i = 0; i < medicineIds.size(); i++) {
            prescriptionMedicine.setPrescriptionId(prescriptionId);
            prescriptionMedicine.setUserId(prescriptionMedicineVO.getUserId());
            prescriptionMedicine.setMedicineId(medicineIds.get(i));
            prescriptionMedicine.setPurchasedNumber(purchasedNumbers.get(i));
            operationMapper.insertPrescriptionMedicine(prescriptionMedicine);
            // TODO 减少药品库存
        }
    }

    /**
     * 增加一个处方表
     * @param
     * @return 受影响的行数
     */
    @Override
    public int insertPrescription(PrescriptionVO prescriptionVO) {
        Prescription prescription = new Prescription();
        BeanUtils.copyProperties(prescriptionVO,prescription);
        // TODO 更改用户预约状态 目前预约表id写死
        operationMapper.updateOrderSettingStateToFinishOrder(1);
        return operationMapper.insertPrescription(prescription);
    }

    /**
     * 根据医生提供的表单为患者安排检查
     * @param patientCheckItemDTO 患者的检查项
     * @return 受影响的行数
     */
    @Override
    public int insertCheckForPatient(PatientCheckItemDTO patientCheckItemDTO) {
        PatientCheckItem patientCheckItem = new PatientCheckItem();
        BeanUtils.copyProperties(patientCheckItemDTO,patientCheckItem);
        return operationMapper.insertCheckForPatient(patientCheckItem);
    }

    /**
     * 插入患者信息
     * @param simpleInfoDTO 患者基本信息
     * @return 患者信息
     */
    @Override
    public PatientSimpleInfoVO insertPatientInfo(PatientSimpleInfoDTO simpleInfoDTO){
        if(operationMapper.insertPatientInfo(simpleInfoDTO) != 1){
            throw new HisServiceException(ResponseCode.INSERT_PATIENT_INFO_ERROR, "新增患者失败!");
        }
        return operationMapper.getPatientInfoByIdCard(simpleInfoDTO.getIdCard());
    }

    /**
     * 插入预约信息
     * @param orderSettingDTO 简单信息
     * @return 受影响行数
     */
    public int insertOrderSetting(OrderSettingDTO orderSettingDTO){
        orderSettingDTO.setState(0);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化时间
//        Date date = new Date();// 获取当前时间
        Calendar date = Calendar.getInstance();
        orderSettingDTO.setOrderTime(sdf.format(date.getTimeInMillis()));
        return operationMapper.insertOrderSetting(orderSettingDTO);
    }

    /**********************************  delete   *********************************/
    /**
     * 通过id删除预约信息
     * @param id 预约的id
     * @return  受影响行数
     */
    @Override
    public int deleteOrderSettingById(Integer id){
        int integer = operationMapper.deleteOrderSettingById(id);
        if(integer == 1){
//            logService.insertOperationLog(123,"删除","删除预约信息");
            return integer;
        }else{
            throw new HisServiceException(ResponseCode.DELETE_ORDER_SETTING_ERROR, "删除失败!");
        }
    }

    /**
     *通过id 删除患者信息
     * @param id 患者id
     * @return 受影响行数
     */
    public int deletePatientInfoById(Integer id){
        int i = operationMapper.deletePatientInfoById(id);
        if(i == 1){
            return i;
        }else{
            throw new HisServiceException(ResponseCode.DELETE_PATIENT_INFO_ERROR, "删除患者失败");
        }
    }


    /**********************************  update   *********************************/

    /**
     * 收费时根据处方表id修改患者缴费状态
     * @param id 处方单id
     * @return 受影响的行数
     */
    @Override
    public void updatePrescriptionStateById(Integer id) {
        operationMapper.updatePrescriptionStateById(id);
    }

    /**
     * 根据患者id修改患者信息并返回患者基本信息
     * @param simpleInfoDTO 患者基本信息
     * @return 患者基本信息
     */
    @Override
    public PatientSimpleInfoVO updatePatientInfoByIdCard(PatientSimpleInfoDTO simpleInfoDTO){
        int i = operationMapper.updatePatientInfoByIdCard(simpleInfoDTO);
        if(i == 1){
            log.info("更改成功");
            return operationMapper.getPatientInfoByIdCard(simpleInfoDTO.getIdCard());
        }else{
            throw new HisServiceException(UPDATE_PATIENT_INFO_ERROR, "修改用户信息失败!");
        }
    }

    /**
     * 根据预约表的id修改预约状态(就诊中)
     * @param  id 预约表id
     * @return 受影响行数
     */
    @Override
    public int updateOrderSettingStateToSeeing(Integer id){
        int i = operationMapper.updateOrderSettingStateToSeeing(id);
        if(i == 1){
            log.info("更改成功");
            return 1;
        }else{
            throw new HisServiceException(UPDATE_PATIENT_INFO_ERROR, "修改用户信息失败!");
        }
    }


    /**********************************  select   *********************************/


    /**
     * 根据医生的id查询预约该医生的预约信息
     * @param searchOrderVO 搜索条件
     * @return  预约信息
     */
    @Override
    public JsonPage<OrderSettingVO> getOrderSettingByDoctorId(SearchOrderVO searchOrderVO){
        log.info("searchOrderVO: {}", searchOrderVO);
        if (searchOrderVO.getPatientId() == ""){
            searchOrderVO.setPatientId(null);
        }
        if("self".equals(searchOrderVO.getCategory())){
            searchOrderVO.setDoctorId(1);
        }
        PageHelper.startPage(searchOrderVO.getPageNum(), searchOrderVO.getPageSize());
        List<OrderSettingVO> list = operationMapper.getOrderSettingByDoctorId(searchOrderVO);
        return JsonPage.restPage(new PageInfo<>(list));
    }

//
//    /**
//     * 根据医生的id查询该医生的排班信息
//     * @param doctorId 医生id
//     * @param pageNum 页号
//     * @param pageSize 每页大小
//     * @return 所有排班信息
//     */
//    @Override
//    public JsonPage<SchedulingVO> getSchedulingByDoctorId(Integer pageNum, Integer pageSize, Integer doctorId) {
//        log.info("pageNum :  {}  pageSize: {}", pageNum, pageSize);
//        PageHelper.startPage(pageNum, pageSize);
//        List<SchedulingVO> list = operationMapper.getSchedulingByDoctorId(doctorId);
//        return JsonPage.restPage(new PageInfo<>(list));
//    }


    /**
     * 根据患者身份证查询患者病历
     * @param idCard 患者身份证
     * @param pageNum 页号
     * @param pageSize 每页大小
     * @return 病历单
     */
    @Override
    public JsonPage<MedicalRecordVO> getMedicalRecordByIdCard(Integer pageNum, Integer pageSize, String idCard){
        PageHelper.startPage(pageNum, pageSize);
        List<MedicalRecordVO> list = operationMapper.getMedicalRecordByIdCard(idCard);
        return JsonPage.restPage(new PageInfo<>(list));
    }

    /**
     * 根据患者就诊卡号查询基本信息
     * @param patientId 就诊卡号
     * @return 患者简单信息
     */
    @Override
    public PatientSimpleInfoVO getPatientInfoByPatientId(Integer patientId){
        PatientSimpleInfoVO patientInfoByPatientId = operationMapper.getPatientInfoByPatientId(patientId);
        log.info("patientInfoByPatientId: {}", patientInfoByPatientId);
        if(patientInfoByPatientId == null){
            throw new HisServiceException(ResponseCode.PATIENT_INFO_NOT_FOUND, "该就诊卡号不存在!");
        }else{
            return patientInfoByPatientId;
        }
    }

    /**
     * 根据患者身份证查询基本信息
     * @param idCard 身份证id
     * @return 患者简单信息
     */
    @Override
    public PatientSimpleInfoVO getPatientInfoByIdCard(String idCard){
        PatientSimpleInfoVO patientInfoByIdCard = operationMapper.getPatientInfoByIdCard(idCard);
        if(patientInfoByIdCard != null){
            throw new HisServiceException(ResponseCode.PATIENT_INFO_ALREADY_EXIST, "该用户已存在!");
        }else{
            return null;
        }
    }

    /**
     * 查询所有科室信息
     * @return 科室列表
     */
    @Override
    public List<RoomVO> getRoomSimpleInfo() {
        List<RoomVO> roomSimpleInfo = operationMapper.getRoomSimpleInfo();
        List<OutpatientServiceVO> outpatientServiceSimpleInfo = operationMapper.getOutpatientServiceSimpleInfo();
        log.info("roomSimpleInfo:{}",roomSimpleInfo);
        log.info("outpatientServiceSimpleInfo:{}",outpatientServiceSimpleInfo);
        for (RoomVO roomVO : roomSimpleInfo) {
            for (OutpatientServiceVO outpatientServiceVO : outpatientServiceSimpleInfo) {
                if(outpatientServiceVO.getRoomId().equals(roomVO.getId())){
                    if(roomVO.getOutpatientServiceList() == null){
                        List<OutpatientServiceVO> list = new ArrayList<>();
                        list.add(outpatientServiceVO);
                        roomVO.setOutpatientServiceList(list);
                    }else{
                        roomVO.getOutpatientServiceList().add(outpatientServiceVO);
                    }

                }
            }
        }
        return roomSimpleInfo;
    }

    /**
     * 根据科室查询医生信息
     * @param roomId 科室id
     * @return 医生列表
     */
    @Override
    public List<DoctorSimpleVO> getDoctorListByRoomId(Integer roomId) {
        // 获取当前时间
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");// 格式化时间
        Calendar date = Calendar.getInstance();
        date.add(Calendar.MINUTE, 10);
        log.info("date:{}" , date);
        log.info("week:{}", date.get(Calendar.DAY_OF_WEEK));



        // 获得需要查询的条件
        DoctorListDTO doctorListDTO = new DoctorListDTO();
        doctorListDTO.setRoomId(roomId);
//        doctorListDTO.setRoomId(3);

        doctorListDTO.setDayId((date.get(Calendar.DAY_OF_WEEK) - 1) == 0 ? 7 : (date.get(Calendar.DAY_OF_WEEK) - 1));

        log.info("hour:{}", date.get(Calendar.HOUR_OF_DAY));
        log.info("min:{}", date.get(Calendar.MINUTE));
        log.info("time:{}", date.get(Calendar.DATE));
        log.info("sdf:{}", sdf.format(date.getTimeInMillis()));
        Integer hour = date.get(Calendar.HOUR_OF_DAY);
        String start = ((hour / 4) * 4) + ":00";
        String end = (((hour / 4) + 1) * 4) + ":00";
        hour = ((hour / 4) + 1);

        log.info("hour:{}" ,hour);

        doctorListDTO.setScheduleId(hour);

        //获取医生列表
        List<DoctorSimpleTempVO> doctorListByRoomId = operationMapper.getDoctorListByRoomId(doctorListDTO);

        log.info("doctorListByRoomId:{}" , doctorListByRoomId);
        log.info("doctorListDTO:{}" , doctorListDTO);


        List<DoctorSimpleVO> doctorSimpleVOS = new ArrayList<>();
        for (DoctorSimpleTempVO doctorSimpleTempVO : doctorListByRoomId) {

            int count = operationMapper.getDoctorCountByDoctorId(doctorSimpleTempVO.getId());
            DoctorSimpleVO doctorSimpleVO = new DoctorSimpleVO();
            BeanUtils.copyProperties(doctorSimpleTempVO, doctorSimpleVO);
            doctorSimpleVO.setRegisteredNumbers(count);
            if("主任医师".equals(doctorSimpleTempVO.getProfessionalTitle())){
                doctorSimpleVO.setConsultationFee(300.0);
            }else{
                doctorSimpleVO.setConsultationFee(5.0);
            }
            doctorSimpleVOS.add(doctorSimpleVO);
        }
        return doctorSimpleVOS;
    }


    /**
     * 根据就诊卡号查询患者历史患病信息
     * @param id 就诊卡号
     * @return 历史患病信息
     */
    @Override
    public List<PersonalSickRecordVO> getPatientSickRecordById(Integer id) {
        // 查询患者过敏信息
        String patientAllergen = operationMapper.getPatientAllergenById(id);
        // 查询患者历史患病信息
        List<PersonalSickRecordVO> patientSickRecords = operationMapper.getPatientSickRecordById(id);
        for (PersonalSickRecordVO personalSickRecord : patientSickRecords) {
            personalSickRecord.setAllergen(patientAllergen);
        }
        return patientSickRecords;
    }

    /**
     * 根据医生的id查询该医生的排班信息
     * @param doctorId 医生id
     * @param pageNum 页号
     * @param pageSize 每页大小
     * @return 所有排班信息
     */
    @Override
    public JsonPage<SchedulingVO> getSchedulingByDoctorId(Integer pageNum, Integer pageSize, Integer doctorId) {
        PageHelper.startPage(pageNum, pageSize);
        List<SchedulingVO> list = operationMapper.getSchedulingByDoctorId(doctorId);
        return JsonPage.restPage(new PageInfo<>(list));
    }

    /**
     * 查询当天预约人数
     * @return 人数
     */
    @Override
    public int getOrderSettingCount(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化时间
        Calendar date = Calendar.getInstance();
        String format = sdf.format(date.getTimeInMillis());
        String time = format.split(" ")[0];
        log.info("time:{}", time);
        String start = time + " 00:00:00";
        String end = time + " 23:59:59";
        log.info("start:{}", start);
        log.info("end:{}", end);
        return operationMapper.getOrderSettingCount(start, end);
    }

    /**
     * 查询当天预约人数
     * @return 人数
     */
    @Override
    public int getFinishOrderSettingCount(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化时间
        Calendar date = Calendar.getInstance();
        String format = sdf.format(date.getTimeInMillis());
        String time = format.split(" ")[0];
        log.info("time:{}", time);
        String start = time + " 00:00:00";
        String end = time + " 23:59:59";
        log.info("start:{}", start);
        log.info("end:{}", end);
        return operationMapper.getFinishOrderSettingCount(start, end);
    }

    /**
     * 根据时间查询近一个月各门诊的预约人数
     * @return 对应的数
     */
    @Override
    public List<OrderSettingServiceVO> getOrderSettingServiceCount(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化时间
        Calendar date = Calendar.getInstance();
        log.info("month1:{}",date.get(Calendar.MONTH));
        date.add(Calendar.MONTH, -1);
        log.info("month2:{}",date.get(Calendar.MONTH));
        String format = sdf.format(date.getTimeInMillis());
        log.info("date:{}",format);
        return operationMapper.getOrderSettingServiceCount(format);
    }

    /**
     * 查询近七天的就诊人数
     * @return map
     */
    @Override
    public List<Map<String, String>> getCountOfNearlySevenDayOrYesterday(Integer time){
        String[] weeks = {"日","一","二","三","四","五","六"};
        Calendar date = Calendar.getInstance();
        SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd");
        if(time == 7){
            List<Map<String, String>> countOfNearlySevenDay = operationMapper.getCountOfNearlySevenDay();
            Collections.sort(countOfNearlySevenDay, new Comparator<Map<String, String>>() {
                @Override
                public int compare(Map<String, String> o1, Map<String, String> o2) {
                    long time1 = 0;
                    long time2 = 0;
                    try {
                        time1 = format.parse(o1.get("time")).getTime();
                        time2 = format.parse(o2.get("time")).getTime();
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    if(time1 > time2){
                        return 1;
                    }else{
                        return -1;
                    }
                }
            });

            for (Map<String, String> stringIntegerMap : countOfNearlySevenDay) {
                log.info("stringIntegerMap:{}",stringIntegerMap);
                try {
                    date.setTime(format.parse(stringIntegerMap.get("time")));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int week = date.get(Calendar.DAY_OF_WEEK) - 1;
                log.info("week:{}", weeks[week]);
                String temp = stringIntegerMap.get("time");
                stringIntegerMap.put("time",temp.split("-")[1] + "-" + temp.split("-")[2] + "(" + weeks[week] + ")");
            }
            log.info("sevenDay:{}", countOfNearlySevenDay);


            log.info("countOfNearlySevenDay:{}", countOfNearlySevenDay);
            return countOfNearlySevenDay;
        }else if(time == 1){
            List<Map<String, String>> countOfYesterday = operationMapper.getCountOfYesterday();
            log.info("sevenDay:{}", countOfYesterday);
            return countOfYesterday;
        }
        return null;
    }

    /**
     * 查询将要过期的药(30天)
     * @return 将要过期的药
     */
    @Override
    public List<MedicineSimpleVO> getMedicineThatWillExpire(){
        List<MedicineSimpleVO> willExpire = operationMapper.getMedicineThatWillExpire();
        SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd");
        for (MedicineSimpleVO medicineSimpleVO : willExpire) {
            Date dateNow = new Date();
            Date parse = null;
            try {
                parse = format.parse(medicineSimpleVO.getExpirationTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            int timeDistance = getTimeDistance(dateNow, parse);
            medicineSimpleVO.setSurplusDay(timeDistance);
            log.info("medicineSimpleVO: {}", medicineSimpleVO);
        }
        return willExpire;
    }

    /**
     * 查询数量少的药(少于10)
     * @return 少于10的药
     */
    @Override
    public List<MedicineSimpleVO> getMedicineThatLessNumbers(){
        return operationMapper.getMedicineThatLessNumbers();
    }


    /**
     * 根据科室id查询所有医生
     * @param roomId 科室id
     * @return 所有医生
     */
    @Override
    public List<DoctorDetailVo> getDoctorDetailByRoomId(Integer roomId){
        return operationMapper.getDoctorDetailByRoomId(roomId);
    }

    /**
     * 根据电话号码查询患者
     * @param number 电话号码
     * @return 患者信息
     */

    @Override
    public List<PatientInfoVO> getPatientByTelephone(String number){
        return operationMapper.getPatientByTelephone(number);
    }


    /**
     * 通过id 修改患者信息
     * @param patientInfoVO 要修改的信息
     * @return 受影响行数
     */
    @Override
    public int updatePatientInfoById(PatientInfoVO patientInfoVO){
        int i = operationMapper.updatePatientInfoById(patientInfoVO);
        if(i == 1){
            return i;
        }else{
            throw new HisServiceException(ResponseCode.UPDATE_PATIENT_INFO_ERROR,"修改失败");
        }

    }


    public int getTimeDistance(Date beginDate , Date endDate ) {
        Calendar beginCalendar = Calendar.getInstance();
        beginCalendar.setTime(beginDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        long beginTime = beginCalendar.getTime().getTime();
        long endTime = endCalendar.getTime().getTime();
        int betweenDays = (int)((endTime - beginTime) / (1000 * 60 * 60 *24));//先算出两时间的毫秒数之差大于一天的天数

        endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays);//使endCalendar减去这些天数，将问题转换为两时间的毫秒数之差不足一天的情况
        endCalendar.add(Calendar.DAY_OF_MONTH, -1);//再使endCalendar减去1天
        if(beginCalendar.get(Calendar.DAY_OF_MONTH)==endCalendar.get(Calendar.DAY_OF_MONTH))//比较两日期的DAY_OF_MONTH是否相等
            return betweenDays + 1;	//相等说明确实跨天了
        else
            return betweenDays + 0;	//不相等说明确实未跨天
    }


    /**
     * 根据电话号码查询预约信息
     * @param telephone 电话号码
     * @return 患者预约信息
     */
    @Override
    public List<OrderSettingVO> getOrderSettingVOByTelephone(String telephone){
        return operationMapper.getOrderSettingVOByTelephone(telephone);
    }


    /**
     * 根据电话查询患者病史
     * @param telephone 电话号码
     * @return 患者病历
     */
    @Override
    public List<MedicalHistoryVO> getMedicalHistoryByTelephone(String telephone){
        return operationMapper.getMedicalHistoryByTelephone(telephone);
    }

    /**
     * 根据电话查询患者就诊报告
     * @param telephone 电话
     * @return 就诊报告
     */
    @Override
    public List<MedicalReportVO> getMedicalReportByTelephone(String telephone){
        return operationMapper.getMedicalReportByTelephone(telephone);
    }

    /**
     * 根据id查询患者信息(传参使用)
     * @param id 患者id
     * @return 患者信息
     */
    @Override
    public PatientVO getPatientInfoById(Integer id){
        return operationMapper.getPatientInfoById(id);
    }


    /**
     * 查询所有药品信息
     * @return 所有药品
     */
    @Override
    public List<MedicineDetailsVO> getMedicineList() {
        return affairService.getMedicineList();
    }

    /**
     * 根据关键字查询药品信息
     * @param name 药品名
     * @return 符合条件的药品
     */
    @Override
    public List<MedicineDetailsVO> getMedicineListByName(String name) {
        return affairService.getMedicineByKeyword(name);
    }

}
